package spring.cloud.tasks.tasks_manager.listener;

import lombok.extern.slf4j.Slf4j;
import spring.cloud.tasks.common.curator.Curator;
import spring.cloud.tasks.common.nodepaths.TaskInstanceNodePaths;
import spring.cloud.tasks.common.status.TaskInstanceInfoStatus;
import spring.cloud.tasks.common.task_item_allot.Executor;
import spring.cloud.tasks.common.task_item_allot.TaskItem;
import spring.cloud.tasks.tasks_manager.schedule.ScheduleManager;
import spring.cloud.tasks.tasks_manager.schedule.TaskInstanceInfo;
import spring.cloud.tasks.tasks_manager.task_item_assign.ExecutorTaskItemListContext;
import spring.cloud.tasks.tasks_manager.task_item_assign.PreferExecutorSettings;
import spring.cloud.tasks.tasks_manager.task_item_assign.TaskItemAssignUtils;
import spring.cloud.tasks.tasks_manager.task_item_assign.TaskItemContainer;

import java.util.*;

@Slf4j
public class TaskDisableOrTaskInstanceStopTaskItemAssign {
    /**
     * @param scheduleManager
     * @param taskId          如果没有实例id那么则是停止一个任务的所有实例
     * @param taskInstanceId  如果有实例Id那么则停止该任务的一个实例
     */
    public Set<String> taskItemAssign(ScheduleManager scheduleManager, String taskId, String taskInstanceId) {
        Curator curator = scheduleManager.curator;
        TaskItemContainer taskItemContainer = scheduleManager.taskItemContainer;
        ExecutorTaskItemListContext assignedExecutorTaskItemListContext = taskItemContainer.assignedExecutorTaskItemListContext;
        PreferExecutorSettings preferExecutorSettings = assignedExecutorTaskItemListContext.preferExecutorSettings;
        if (preferExecutorSettings == null) {
            return new HashSet<>();//如果这个参数没有则代表还没有进行预分配,那么就不进行后续操作了。
        }
        /**
         * 正在调度分配的任务分片容器
         */
        List<Executor> oldOnlineExecutorList = assignedExecutorTaskItemListContext.getExecutorList();

        ExecutorTaskItemListContext assigningExecutorTaskItemListContext = new ExecutorTaskItemListContext();
        assigningExecutorTaskItemListContext.setExecutorList(TaskItemAssignUtils.copyExecutorList(oldOnlineExecutorList));
        List<Executor> onlineExecutorList = assigningExecutorTaskItemListContext.getExecutorList();
        List<TaskItem> pickUpEdTaskItemList = new ArrayList<>();
        Iterator<Executor> iterator = onlineExecutorList.iterator();
        Set<String> taskInstanceIdSet = new HashSet<>();//当taskInstanceId==null时使用。
        while (iterator.hasNext()) {
            Executor executor = iterator.next();
            List<TaskItem> taskItemList = executor.getTaskItemList();
            Iterator<TaskItem> iterator1 = taskItemList.iterator();
            while (iterator1.hasNext()) {
                TaskItem taskItem = iterator1.next();
                if (taskId.equals(taskItem.getTaskId())) {
                    if (taskInstanceId != null) {
                        if (taskItem.getTaskInstanceId().equals(taskInstanceId)) {
                            iterator1.remove();
                            pickUpEdTaskItemList.add(taskItem);
                            //
                            taskInstanceIdSet.add(taskItem.getTaskInstanceId());
                        }
                    } else {
                        iterator1.remove();
                        pickUpEdTaskItemList.add(taskItem);
                        //
                        taskInstanceIdSet.add(taskItem.getTaskInstanceId());
                    }
                }
            }
        }
        taskItemContainer.assignedExecutorTaskItemListContext = assigningExecutorTaskItemListContext;
        return taskInstanceIdSet;
    }

    public void taskInstanceStausUpdate(ScheduleManager scheduleManager, String taskId, String taskType, String stateFullTask, Set<String> taskInstanceIdSet) {
        Curator curator = scheduleManager.curator;
        //这里需要区分任务类型。是简单的分片任务还是批次任务。
        List<TaskInstanceInfo> taskInstanceInfoList = new ArrayList<>(taskInstanceIdSet.size());
        List<String> taskInstanceIdList = new ArrayList<>(taskInstanceIdSet.size() / 4 + 1);
        for (String taskInstanceId : taskInstanceIdSet) {
            //先更新ZK，再更新内存。即使失败了，那么主预分配程序也可以修正。
            TaskInstanceInfo taskInstanceInfo = TaskItemAssignUtils.getTaskInstanceInfo(scheduleManager, taskId, taskType, stateFullTask, taskInstanceId);
            if (taskInstanceInfo != null) {
                taskInstanceInfoList.add(taskInstanceInfo);
            } else {
                taskInstanceIdList.add(taskInstanceId);
            }
        }
        for (TaskInstanceInfo taskInstanceInfo : taskInstanceInfoList) {
            updateInstanceStatusWhenUserCancel(scheduleManager, curator, taskId, taskInstanceInfo);
        }
    }

    public void updateInstanceStatusWhenUserCancel(ScheduleManager scheduleManager, Curator curator, String taskId, TaskInstanceInfo taskInstanceInfo) {
        String taskInstanceId = taskInstanceInfo.getTaskInstanceId();
        try {
            String taskInstanceNodePath = TaskInstanceNodePaths.getTaskInstanceNodePath(taskId, taskInstanceId);
            String taskInstanceStatusNodePath = TaskInstanceNodePaths.getTaskInstanceSubNodePath(taskId, taskInstanceId, TaskInstanceNodePaths.TaskInstanceSubNode.status);
            String string = curator.getData(taskInstanceNodePath);
            if (string == null) {
                String newStatus = TaskInstanceInfoStatus.user_cancel;
                curator.merge(taskInstanceStatusNodePath, newStatus);
                taskInstanceInfo.setStatus(newStatus);
                TaskItemAssignUtils.updateInstanceStatusWhenUserCancel(scheduleManager, taskId, taskInstanceId, newStatus);
                taskInstanceInfo.setStatus(newStatus);
            } else {

                if (TaskInstanceInfoStatus.waiting_task_item_pre_assign_success.equals(string)) {
                    String newStatus = TaskInstanceInfoStatus.user_cancel;
                    curator.merge(taskInstanceStatusNodePath, newStatus);
                    taskInstanceInfo.setStatus(newStatus);
                    TaskItemAssignUtils.updateInstanceStatusWhenUserCancel(scheduleManager, taskId, taskInstanceId, newStatus);
                    taskInstanceInfo.setStatus(newStatus);
                } else {
                    //已经取消了
                }
            }


        } catch (Exception e) {

        }
    }
}
